 /*      SVMachine.cpp
 *
 *      Copyright 2009-2010 virpool <virpool@ukrpost.ua>
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */

#include "SVMachine.h"
#include <readline/readline.h>
#include <readline/history.h>

SVMachine* SVMachine::__instance;


SVMachine::SVMachine()
{
	SGarbageCollector::Start();
	level = max_level = args_flags_p = 0;
	comm_deep = value_deep = 0;
	e_deep = 1;
	global = new SRegistryObj *[255];
	global[0] = new SRegistryObj();
	SGarbageCollector::AddToCache(global[0]);
}

SVMachine::~SVMachine()
{
	SGarbageCollector::Stop();
	for (unsigned int i = 0; i < max_level; i++)
	{
		delete global[i];
	}
	delete [] global;
}

SVMachine* SVMachine::GetInstance()
{
	if (__instance == NULL)
	{
		__instance = new SVMachine();
	}
	return __instance;
}

void SVMachine::Release()
{
	if (__instance)
	{
		delete __instance;
		__instance = NULL;
	}
}

bool SVMachine::Execute()
{
	list<s_command*>::iterator c;
	bool flag = false;
	int i_max = 0, i_cnt = 0;
	if (comm_deep && comm_cache[comm_deep-1].size())
	{
		i_max = comm_cache[comm_deep-1].size();
		c = comm_cache[comm_deep-1].begin();
		flag = true;
	}
	else
	{
		c = commands.begin();
		i_max = commands.size();
	}
	while (c != (flag == false ? commands.end(): comm_cache[comm_deep-1].end()) && i_cnt < i_max)
	{
		cur_comm = *c;
		if (is_break)
		{
			if (cur_comm->parent && (cur_comm->parent->comm == s_while || cur_comm->parent->comm == s_for || cur_comm->parent->comm == s_for_cont))
			{
				cur_comm->parent->breaking = true;
				break;
			}
			else
				is_break = false;
		}
		
		switch ((*c)->comm)
		{
			case s_new:
				new_object();
				break;
			case s_delete:
				delete_operation();
				break;
			case s_mov:
				break;
			case s_put:
			case s_puts:
				put_operation();
				break;
			case s_input:
				input();
				break;
			case s_operation:
				operation_handler();
				break;
			case s_expr:
				expression_operarion();
				break;
			case s_if:
				if_operation();
				break;
			case s_while:
				while_operation();
				break;
			case s_for:
				if ((*c)->for_type)
					for_operation_foreach();
				else
					for_operation_smpl();
				break;
			case s_for_cont:
				for_cont_operation();
				break;
			case s_break:
				is_break = true;
				break;
			case s_method:
				method_handler();
				break;
			default: break;
		
		}
		c++; i_cnt++;
	}
	if (! flag)
		commands.clear();
	else
		comm_cache[comm_deep-1].clear();
}


void SVMachine::new_object()
{
	if (!cur_comm->is_var)
	{
		if (!cur_comm->is_obj)
		{
			std::string objname;
			SObject *obj2;
			if ( get_subobject(&objname, obj2) )
			{
				if (check_object(objname, ((SClassObject*)obj2)->GetFields()))
				{
					cerr << "\nObject with identity = '" << objname.c_str() << "' already exists!\n";
				}
				else
				{
					create_object( objname, ((SClassObject*)obj2)->GetFields() );
				}
			}
		}
		else
		{
			std::string objname;
			SObject *obj2;
			if ( get_subobject(&objname, obj2) )
			{
				if (check_object(objname, ((SClassObject*)obj2)->GetFields()))
				{
					cerr << "\nObject with identity = '" << objname.c_str() << "' already exists!\n";
				}
				else
				{
					SClassObject *obj = new SClassObject(objname);
					((SClassObject*)obj2)->GetFields()->Add(objname, obj);
				}
			}
		}
	}
	else
	{
		if (!cur_comm->value)
		{
			if (!cur_comm->is_obj)
			{
				std::string objname = cur_comm->obj_id;
				if (check_object(objname, global[level]))
				{
					cerr << "\nObject with identity = '" << objname.c_str() << "' already exists!\n";
				}
				else
				{
					create_object( objname, global[level] );
				}
			}
			else
			{
				std::string objname = cur_comm->obj_id;
				if (check_object(objname, global[level]))
				{
					cerr << "\nObject with identity = " << objname.c_str() << "already exists!\n";
				}
				else
				{
							
					SClassObject *obj = new SClassObject(objname);
					global[level]->Add(objname, obj);
				}
			}
		}
		else
		{
			std::string pobjname, objname;
			SObject *pobj, *pbj;
				
			objname = cur_comm->obj_id;
			if ( ! get_subobject(&pobjname, pobj) )
			{
				cerr << "Error. Can't find object from right side!.\n";
			}
			else
			{
				std::string potype = pobj->GetClassName();
				if (potype == "Integer")
				{
					cur_comm->arg_type = S_INT;
					cur_comm->val_int = ((SClassInteger*) pobj)->Get();
				} else if (potype == "Float")
				{
					cur_comm->arg_type = S_FLOAT;
					cur_comm->val_float = ((SClassFloat*) pobj)->Get();
				} else if (potype == "String") 
				{
					cur_comm->arg_type = S_STRING;
					cur_comm->val_string = ((SClassString*) pobj)->Get();
				} else if (potype == "Boolean")
				{
					cur_comm->arg_type = S_BOOL;
					cur_comm->val_bool = ((SClassBoolean*) pobj)->Get();
				} else
				{
					cerr << "Incorrect right side! Creation simple object.\n";
					SClassObject *obj = new SClassObject(objname);
					global[level]->Add(objname, obj);
					return;
				}
				create_object( objname, global[level] );
			}
		}
	}
}

void SVMachine::operation_handler()
{
	s_command *p = cur_comm;
	
	if (cur_comm->tmpbuf.size())
	{
		list<string>::iterator tp = cur_comm->tmpbuf.begin();
		while (tp != cur_comm->tmpbuf.end())
		{
			cur_comm->buf.push_back(*tp);
			tp++;
		}
	}
	
	if (cur_comm->child.size())
	{
		comm_cache[comm_deep++] = cur_comm->child;
		Execute();
		comm_deep--;
	}
	cur_comm = p;
	if (!cur_comm->is_array_operation && !cur_comm->is_hash_operation)
	{
		operation(cur_comm->is_string, cur_comm->is_params);
	}
	else
	{
		list<string>::iterator p = cur_comm->buf.begin();
		std::string on;
		SObject *obj = NULL;
		get_subobject(&on, obj);
		if ( cur_comm->is_array_operation && obj && obj->GetClassName() == "Array" )
		{
			SObject *o = ((SClassArray*)obj)->Get(cur_comm->array_indx);
			if (o == NULL)
			{	
				cerr << "Exit from array bounds!\n";
			}
			else
			{
				s_param buf;
				o->Invoke("ToString", &buf, 0);
				stdout_buf.push_back((*(string*)buf.val));
			}		
		} 
		else if (obj && obj->GetClassName() == "Hash" && (cur_comm->is_hash_operation || cur_comm->hash_key != ""))
		{
			SObject *o = ((SClassHash*)obj)->Get(cur_comm->hash_key);
			if (o == NULL)
			{	
				cerr << "No key in hash!\n";
			}
			else
			{
				s_param buf;
				o->Invoke("ToString", &buf, 0);
				stdout_buf.push_back((*(string*)buf.val));
			}
		}
		else
		{
		}
	}
	args.clear();

}

void SVMachine::create_object(std::string name, SRegistryObj *reg, s_param *val)
{
	switch(cur_comm->arg_type) 
	{
		case S_INT:
		{
			SClassInteger *obj = new SClassInteger(name);
			if (cur_comm->is_value)
			{
				obj->Set(cur_comm->val_int);
			}
			if (val)
			{
				if (val->type == S_INT)
				{
					obj->Set(*((int*)val->val));
				}
				else
				{
					if (val->type == S_OBJECT)
					{
						SObject *init = (SObject*) val->val;
						if (init->GetClassName() == "Integer")
							obj->Set( ((SClassInteger*) init)->Get() );
						else
							cerr << "local object initializer must be Integer!.\n";
					}
					else
						cerr << "local object initializer must be Integer!.\n";
				}
			}
			reg->Add(name, obj);
			break;
		}
		case S_FLOAT:
		{
			SClassFloat *obj = new SClassFloat(name);
			if (cur_comm->is_value)
			{
				obj->Set(cur_comm->val_float);
			}
			if (val)
			{
				if (val->type == S_FLOAT)
				{
					obj->Set(*((double*)val->val));
				}
				else
				{
					if (val->type == S_OBJECT)
					{
						SObject *init = (SObject*) val->val;
						if (init->GetClassName() == "Float")
							obj->Set( ((SClassFloat*) init)->Get() );
						else
							cerr << "local object initializer must be Float!.\n";
					}
					else
						cerr << "local object initializer must be Float!.\n";
				}
			}
			reg->Add(name, obj);
			break;
		}
		case S_STRING:
		{
			SClassString *obj = new SClassString(name);
			if (cur_comm->is_value)
			{
				obj->Set(cur_comm->val_string);
			}
			if (val)
			{
				if (val->type == S_STRING)
				{
					obj->Set(*((string*)val->val));
				}
				else
				{
					if (val->type == S_OBJECT)
					{
						SObject *init = (SObject*) val->val;
						if (init->GetClassName() == "String")
							obj->Set( ((SClassString*) init)->Get() );
						else
							cerr << "local object initializer must be String!.\n";
					}
					else
						cerr << "local object initializer must be String!.\n";
				}
			}
			reg->Add(name, obj);
			break;
		}
		case S_BOOL:
		{
			SClassBoolean *obj = new SClassBoolean(name);
			if (cur_comm->is_value)
			{
				obj->Set(cur_comm->val_bool);
			}
			if (val)
			{
				if (val->type == S_BOOL)
				{
					obj->Set(*((bool*)val->val));
				}
				else
				{
					if (val->type == S_OBJECT)
					{
						SObject *init = (SObject*) val->val;
						if (init->GetClassName() == "Boolean")
							obj->Set( ((SClassBoolean*) init)->Get() );
						else
							cerr << "local object initializer must be Boolean!.\n";
					}
					else
						cerr << "local object initializer must be Boolean!.\n";
				}
			}
			reg->Add(name, obj);
			break;
		}
		case S_ARRAY:
		{
			SClassArray *obj = new SClassArray(name, ! cur_comm->is_value, cur_comm->arg_type_arr, cur_comm->is_value ? cur_comm->val_int : 0);
			reg->Add(name, obj);
			break;
		}
		case S_HASH:
		{
			SClassHash *obj = new SClassHash(name);
			reg->Add(name, obj);
			break;
		}
		case S_FILE:
		{
			SClassFile *obj = new SClassFile(name);
			reg->Add(name, obj);
			break;
		}
		default:
			cerr << "\nNo specified\n";
			break;
	}
}

void SVMachine::input()
{
	//cerr << "input..\n";
	if (cur_comm->buf.size() == 1) {
		list<string>::iterator p = cur_comm->buf.begin();
		//cerr << "obj = " << *p << endl;
		SObject *o = find_object(*p);
		//if (o) cerr << "obj.\n";
		input_string(o);
	} else {
		std::string objname;
		SObject *obj2;
		if ( get_subobject(&objname, obj2) )
		{
			cerr << objname << endl;
			SObject *o = ((SClassObject*)obj2)->GetFields()->Get(objname);
			input_string(o);
		}
	}
}

void SVMachine::put_operation()
{
	if (cur_comm->child.size())
	{
		comm_cache[comm_deep++] = cur_comm->child;
		Execute();
		comm_deep--;
	}
	else
	{
		if (cur_comm->is_put_single_out)
		{
			if ((cur_comm->parent->comm == s_put || cur_comm->parent->comm == s_puts) && cur_comm->value == false)
			{
				stdout_buf.push_back(cur_comm->out);
			}
			else
			{
				s_param *s = new s_param;
				if (cur_comm->value)
				{
					if (value == NULL)
					{
						cerr << "Incorrect placement of value. terminate\n";
						return;
					}
					std::string vcn = value[value_deep - 1]->GetClassName();
					if (vcn == "Integer") {
						cur_comm->val_int = ((SClassInteger*)value[value_deep - 1])->Get();
						cur_comm->arg_type = S_INT;
						if (cur_comm->parent->comm == s_put || cur_comm->parent->comm == s_puts)
						{
							//stdout_buf.push_back(cur_comm->out);
							return;
						}
					} else if (vcn == "Float") {
						cur_comm->val_float = ((SClassFloat*)value[value_deep - 1])->Get();
						cur_comm->arg_type = S_FLOAT;
						if (cur_comm->parent->comm == s_put || cur_comm->parent->comm == s_puts)
						{
							//stdout_buf.push_back(cur_comm->out);
							return;
						}
					} else if (vcn == "String") {
						cur_comm->val_string = ((SClassString*)value[value_deep - 1])->Get();
						cur_comm->arg_type = S_STRING;
						if (cur_comm->parent->comm == s_put || cur_comm->parent->comm == s_puts)
						{
							stdout_buf.push_back(cur_comm->val_string);
							return;
						}
					} else {
						cerr << "Incorrect value. terminate\n";
						return;
					}
				}
				switch(cur_comm->arg_type)
				{
					case S_INT:
					{
						//cerr << "add new int param\n";
						int *val = new int;
						garbage.push_back(val);
						*val = cur_comm->val_int;
						s->type = S_INT;
						s->val = val;
						expr_val[expr_deep[e_deep - 1]++][e_deep - 1] = cur_comm->val_int;
						//cerr << "ok\n";
						break;
					}
					case S_FLOAT:
					{
						double *val = new double;
						garbage.push_back(val);
						*val = cur_comm->val_float;
						s->type = S_FLOAT;
						s->val = val;
						expr_val[expr_deep[e_deep - 1]++][e_deep - 1] = cur_comm->val_float;
						break;
					}
					case S_STRING:
					{
						std::string *val = new string;
						garbage.push_back(val);
						*val = cur_comm->val_string;
						s->type = S_STRING;
						s->val = val;
						expr_val_str[expr_deep_str[e_deep - 1]++][e_deep - 1] = cur_comm->val_string;
						break;
					}
					case S_BOOL:
					{
						bool *val = new bool;
						garbage.push_back(val);
						*val = cur_comm->val_bool;
						s->type = S_BOOL;
						s->val = val;
						expr_val[expr_deep[e_deep - 1]++][e_deep - 1] = cur_comm->val_bool;
						break;
					}
					default: break;
				}
				args.push_back(*s);
			}
			return;
		} else {
			id_dotlist_handler();
			return;
		}
	}
	if (cur_comm->comm == s_put)
		put_out(false);
	else
		put_out(true);
	stdout_buf.clear();
}

void SVMachine::expression_operarion()
{
	e_deep++;
	if (!cur_comm->is_array)
	{
		std::string cl;
		if (cur_comm->value)
		{
			if (value == NULL)
			{
				cerr << "Incorrect placement of value. terminate\n";
				e_deep--;
				return;
			}
			cl = value[value_deep - 1]->GetClassName();
			cur_comm->expr_obj_left = value[value_deep - 1];
		}
		else
		{
			std::string objname;
			SObject *obj;
			get_subobject(&objname, obj);
			cur_comm->expr_obj_left = obj;
			cl = obj->GetClassName();
		}
		if (cl == "Integer") cur_comm->expr_type = S_INT;
		else if (cl == "Float") cur_comm->expr_type = S_FLOAT;
		else if (cl == "String") cur_comm->expr_type = S_STRING;
		else if (cl == "Boolean") cur_comm->expr_type = S_BOOL;
	}
	else
	{
		prepare_expr_array();
	}

	// caclucate expressions
	s_command *tmp = cur_comm;
	expression_calc();
	
	// final
	cur_comm = tmp;
	if (cur_comm->is_expr_error == true)
	{
		cerr << "expression error: " << cur_comm->last_expr_error << "\n";
	} 
	else
	{
		if (cur_comm->expr_act == e_eq)
		{
			//cerr << "prefinal expr\n";
			switch (cur_comm->expr_type)
			{
				case S_INT:
					//cerr << "this is integer\n";
					((SClassInteger*)cur_comm->expr_obj_left)->Set((int)expr_val[0][e_deep - 1]);
					break;
				case S_FLOAT:
					((SClassFloat*)cur_comm->expr_obj_left)->Set(expr_val[0][e_deep - 1]);
					break;
				case S_STRING:
					((SClassString*)cur_comm->expr_obj_left)->Set(expr_val_str[0][e_deep - 1]);
					break;
				case S_ARRAY:
				{
					SObject *s;
					//cerr << "it's array\n";
					s = ((SClassArray*)cur_comm->expr_obj_left)->Get(cur_comm->is_array_index);
					switch (cur_comm->is_array_type)
					{
						case S_INT:
						{
							//cerr << "it's array with type integer\n";
							((SClassInteger*)s)->Set((int)expr_val[0][e_deep - 1]);
								//s = new SClassInteger("none");
							break;
						}
						default:
							break;
					}
					((SClassArray*)cur_comm->expr_obj_left)->Set(cur_comm->is_array_index, s);
					cur_comm->is_array = false;
					cur_comm->is_array_index = 0;
					break;
				}
				case S_BOOL:
					((SClassBoolean*)cur_comm->expr_obj_left)->Set(expr_val[0][e_deep - 1]);
					break;
				default:
					break;
			}
		}
		else 
		{
			expr_post_handler();
		}
	}
	e_deep--;
	args.clear();
}


void SVMachine::if_operation()
{
	e_deep++;
	//cerr << "child = " << cur_comm->child.size() << " ; alter_child = " << cur_comm->alt_child.size() << " ; if_expr_child = " << cur_comm->if_expr_child.size() << endl;
	s_command *tmp = cur_comm;
	
	expression_calc();
	
	cur_comm = tmp;
	
	if (expr_val[0][e_deep - 1])
	{
		if (cur_comm->child.size())
		{
			comm_cache[comm_deep++] = cur_comm->child;
			Execute();
			comm_deep--;
		}
		cur_comm = tmp;
	}
	else
	{
		if (cur_comm->alt_child.size())
		{
			comm_cache[comm_deep++] = cur_comm->alt_child;
			Execute();
			comm_deep--;
		}
		cur_comm = tmp;
	}
	
	e_deep--;
}

void SVMachine::while_operation()
{
	e_deep++;
	cur_comm->breaking = false;
	
	s_command *tmp = cur_comm;
	expression_calc();
	cur_comm = tmp;
	
	list<s_command*>::iterator p = cur_comm->child.begin();
	
	while (expr_val[0][e_deep - 1])
	{
		if (cur_comm->child.size())
		{
			comm_cache[comm_deep++] = cur_comm->child;
			Execute();
			comm_deep--;
		}
		cur_comm = tmp;
		
		if (cur_comm->breaking)
			break;
		
		expression_calc();
		cur_comm = tmp;
		stdout_buf.clear();
		
	}
	stdout_buf.clear();
	e_deep--;
}

void SVMachine::for_operation_smpl()
{
	cur_comm->breaking = false;
	s_command *p = cur_comm;
	
	e_deep++;
	
	global[++level] = new SRegistryObj(); 
	if (level > max_level) max_level = level;
	
	if (cur_comm->for_init)
	{
		cur_comm = cur_comm->for_init;
		
		new_object();
		
		cur_comm = p;
		
	}
	
	bool q = cur_comm->if_expr_child.size() != 0;

	if ( q )
	{
		cur_comm = p;
	
		expression_calc();
		cur_comm = p;
	
	}
	else
		expr_val[0][e_deep - 1] = 1;
		
	while (expr_val[0][e_deep - 1])
	{
		if (cur_comm->child.size())
		{
			comm_cache[comm_deep++] = cur_comm->child;
			Execute();
			comm_deep--;
			cur_comm = p;
		}
		
		if (cur_comm->alt_child.size())
		{
			comm_cache[comm_deep++] = cur_comm->alt_child;
			Execute();
			comm_deep--;
			cur_comm = p;
		}
		
		if ( q )
		{
			cur_comm = p;
	
			expression_calc();
	
			cur_comm = p;
	
		}
		else
			expr_val[0][e_deep - 1] = 1;
		stdout_buf.clear();
	}
	
	e_deep--;
	
	delete global[level--];
	stdout_buf.clear();
	
}

void SVMachine::for_operation_foreach()
{
	cur_comm->breaking = false;
	s_command *p = cur_comm;
	
	s_command *sc = new s_command;
	sc->buf = cur_comm->coll_id;
	
	std::string val_id = cur_comm->for_init->obj_id;
	
	SObject *coll = NULL;
	std::string coll_name;
	
	cur_comm = sc;
	
	get_subobject(&coll_name, coll);

	if (! coll)
	{
		cerr << "No object! Interupt.\n";
		return;
	}
	
	cur_comm = p;
	
	std::string cc = coll->GetClassName();

	if (cc != "Array" && cc != "Hash")
	{
		cerr << "Collection must be Array or Hash!.\n";
		return;
	}
	
	global[++level] = new SRegistryObj(); 
	if (level > max_level) max_level = level;

	if (cc == "Array")
	{
		
		std::string art = ((SClassArray*)coll)->GetArrayType();
		if (art == "String")
		{
			SObject *obj = new SClassString(val_id);
			global[level]->Add(val_id, obj);
			
			unsigned long bound = ((SClassArray*)coll)->GetSize();
			s_command *prev = cur_comm;
			for (unsigned long i = 0; i < bound; i++)
			{
				((SClassString*)obj)->Set((dynamic_cast<SClassString*>(((SClassArray*)coll)->Get(i)))->Get());
				if (cur_comm->child.size())
				{
					comm_cache[comm_deep++] = cur_comm->child;
					Execute();
					comm_deep--;
				}
				cur_comm = prev;
				stdout_buf.clear();
				
			}
			
		}
		else if (art == "Integer")
		{
			SObject *obj = new SClassInteger(val_id);
			global[level]->Add(val_id, obj);
			
			unsigned long bound = ((SClassArray*)coll)->GetSize();
			s_command *prev = cur_comm;
			for (unsigned long i = 0; i < bound; i++)
			{
				((SClassInteger*)obj)->Set((dynamic_cast<SClassInteger*>(((SClassArray*)coll)->Get(i)))->Get());
				if (cur_comm->child.size())
				{
					comm_cache[comm_deep++] = cur_comm->child;
					Execute();
					comm_deep--;
				}
				cur_comm = prev;
				stdout_buf.clear();
				
			}
		}
		else if (art == "Float")
		{
			SObject *obj = new SClassFloat(val_id);
			global[level]->Add(val_id, obj);
			
			unsigned long bound = ((SClassArray*)coll)->GetSize();
			s_command *prev = cur_comm;
			for (unsigned long i = 0; i < bound; i++)
			{
				((SClassFloat*)obj)->Set((dynamic_cast<SClassFloat*>(((SClassArray*)coll)->Get(i)))->Get());
				if (cur_comm->child.size())
				{
					comm_cache[comm_deep++] = cur_comm->child;
					Execute();
					comm_deep--;
				}
				cur_comm = prev;
				stdout_buf.clear();
				
			}
		}
		else
		{
			cerr << "Only array of Integer, Float or String !\n";
		}
		
	}
	
	delete global[level--];
	
	stdout_buf.clear();
	
}

void SVMachine::for_cont_operation()
{
	s_command *p = cur_comm;
	list<s_command*>::iterator p1 = cur_comm->child.begin();
	if (cur_comm->child.size())
	{
		global[++level] = new SRegistryObj(); 
		if (level > max_level) max_level = level;
		if (cur_comm->parent->comm == s_method)
		{
			if (cur_comm->parent->fparams.size())
			{
				list<s_method_param*>::iterator p = cur_comm->parent->fparams.begin();
				if ((args_flags[args_flags_p - 1] && (cur_comm->parent->fparams.size() != cur_comm->parent->args.size())) || (!args_flags[args_flags_p - 1] && cur_comm->parent->fparams.size() ) )
				{	
					cerr << "incorrect parameters\n\n";
					return;
				}
				else
				{
					param_list::iterator tp;
					if (args_flags[args_flags_p - 1])
						tp = cur_comm->parent->args.begin();
					while ( p != cur_comm->parent->fparams.end() )
					{
						s_command *tmpc = new s_command, *tmp = cur_comm;
						
						tmpc->arg_type = (*p)->type;
						tmpc->is_value = false;
						
						cur_comm = tmpc;
						
						if (! args_flags[args_flags_p - 1])
							create_object( (*p)->id, global[level] );
						else
						{
							create_object( (*p)->id, global[level], &(*tp) );
							tp++;
						}
						cur_comm = tmp;
						
						delete tmpc;
						
						p++;
						
					}
				}
			}
			else
			{
				
			}
		}
		
		comm_cache[comm_deep++] = cur_comm->child;
		Execute();
		comm_deep--;
		delete global[level--];
	}
	cur_comm = p;
}

void SVMachine::call_method(SObject *obj, s_command *method, bool is_args)
{
	value[value_deep++] = obj;
	args_flags[args_flags_p++] = is_args;
	method->args = args;
	comm_cache[comm_deep++] = method->child;
	Execute();
	comm_deep--;
	args_flags_p--;
	value_deep--;
}

void SVMachine::method_handler()
{
	s_command *p = cur_comm;
	cerr << "\tadd new method.: " << cur_comm->out << "\n";
	switch (cur_comm->arg_type)
	{
		case S_INT:
		{
			s_methods::iterator p = t_integer.find(cur_comm->out);
			if (p != t_integer.end())
				cerr << "\tmethod already exists\n";
			else
				t_integer.insert(pair<string, s_command*>(cur_comm->out, cur_comm));
			break;
		}
		case S_FLOAT:
		{
			s_methods::iterator p = t_float.find(cur_comm->out);
			if (p != t_float.end())
				cerr << "\tmethod already exists\n";
			else
				t_float.insert(pair<string, s_command*>(cur_comm->out, cur_comm));
			break;
		}
		case S_STRING:
		{
			s_methods::iterator p = t_string.find(cur_comm->out);
			if (p != t_string.end())
				cerr << "\tmethod already exists\n";
			else
				t_string.insert(pair<string, s_command*>(cur_comm->out, cur_comm));
			break;
		}
		default:
			break;
	}
}

bool SVMachine::test_parent()
{
	return (cur_comm->comm == s_if || cur_comm->comm == s_while || cur_comm->comm == s_for);
}

void SVMachine::expression_calc()
{
	s_command *tmp = cur_comm;
	expr_deep[e_deep - 1] = expr_deep_str[e_deep - 1] = 0;
	
	if (!test_parent())
	{
		if (cur_comm->child.size())
		{
			comm_cache[comm_deep++] = cur_comm->child;
			Execute();
			comm_deep--;
		}
	}
	else
	{
		if (cur_comm->if_expr_child.size())
		{
			comm_cache[comm_deep++] = cur_comm->if_expr_child;
			Execute();
			comm_deep--;
			cur_comm = tmp;
		}
	}
	cur_comm = tmp;
	list<s_comm>::iterator p = cur_comm->expr_stack.begin();
	while (p != cur_comm->expr_stack.end())
	{
		switch (*p)
		{
			case s_land:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
						case S_ARRAY:
						case S_BOOL:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] && expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			case s_lor:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
						case S_ARRAY:
						case S_BOOL:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] || expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			case s_shr:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
							expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = (int)expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] >> (int)expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
							expr_deep[e_deep - 1]--;
							//cerr << "res = " << expr_val[expr_deep-1] << endl;
							break;
						default:
							cerr << "incorrect operands!\n";
					}
				}
				break;
			case s_shl:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
							expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = (int)expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] << (int)expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
							expr_deep[e_deep - 1]--;
							//cerr << "res = " << expr_val[expr_deep-1] << endl;
							break;
						default:
							cerr << "incorrect operands!\n";
					}
				}
				break;
			case s_ge:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
						case S_ARRAY:
						case S_BOOL:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] >= expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
							//	cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			case s_le:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
						case S_ARRAY:
						case S_BOOL:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] <= expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			case s_eq:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
						case S_ARRAY:
						case S_BOOL:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] == expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			case s_ne:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
						case S_ARRAY:
						case S_BOOL:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] != expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			case s_add:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
							if (expr_deep_str[e_deep - 1])
							{
								cur_comm->is_expr_error = true;
								cur_comm->last_expr_error = "incorrect operands";
							}
						case S_ARRAY:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] += expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						case S_STRING:
							expr_val_str[expr_deep_str[e_deep - 1]-2][e_deep - 1] += expr_val_str[expr_deep_str[e_deep - 1]-1][e_deep - 1];
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}
				}
				break;
			case s_sub:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
							if (expr_deep_str[e_deep - 1])
							{
								cur_comm->is_expr_error = true;
								cur_comm->last_expr_error = "incorrect operands";
							}
						case S_ARRAY:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] -= expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
								break;
							}
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}
				}
				break;
			case s_mul:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
						case S_ARRAY:
							if (expr_test_string())
							{
								cur_comm->is_expr_error = true;
								cur_comm->last_expr_error = " detected std::string in expression";
							}
							else
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] *= expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						case S_STRING:
						{
							if (expr_deep[e_deep - 1] != 1)
							{
								cur_comm->is_expr_error = true;
								cur_comm->last_expr_error = "only use: %str = some_str * num";
							}
							else if (expr_deep_str[e_deep - 1] != 1)
							{
								cur_comm->is_expr_error = true;
								cur_comm->last_expr_error = "only use: %str = some_str * num";
							}
							else 
							{
								std::string tmp = expr_val_str[0][e_deep - 1], res;
								for (int i = 0; i < (int)expr_val[0][e_deep - 1]; i++, res += tmp);
								expr_val_str[0][e_deep - 1] = res;
								expr_deep_str[e_deep - 1]--;
							}
							break;
						}
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}
				}
				break;
			case s_div:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
							if (expr_deep_str[e_deep - 1])
							{
								cur_comm->is_expr_error = true;
								cur_comm->last_expr_error = "incorrect operands";
							}
						case S_ARRAY:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] /= expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			case s_mod:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
							if (expr_deep_str[e_deep - 1])
							{
								cur_comm->is_expr_error = true;
								cur_comm->last_expr_error = "incorrect operands";
							}
						case S_ARRAY:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = (int)expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] % (int)expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			case s_or:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
							if (expr_deep_str[e_deep - 1])
							{
								cur_comm->is_expr_error = true;
								cur_comm->last_expr_error = "incorrect operands";
							}
						case S_ARRAY:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = (int)expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] | (int)expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			case s_and:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_ARRAY:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = (int)expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] & (int)expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			case s_xor:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
							if (expr_deep_str[e_deep - 1])
							{
								cur_comm->is_expr_error = true;
								cur_comm->last_expr_error = "incorrect operands";
							}
						case S_ARRAY:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = (int)expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] ^ (int)expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			case s_g:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
						case S_ARRAY:
						case S_BOOL:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] > expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			case s_l:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
						case S_ARRAY:
						case S_BOOL:
							if (cur_comm->is_expr_error == false)
							{
								expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] = expr_val[expr_deep[e_deep - 1]-2][e_deep - 1] < expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			case s_minus:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
							if (expr_deep_str[e_deep - 1])
							{
								cur_comm->is_expr_error = true;
								cur_comm->last_expr_error = "incorrect operands";
							}
							else
							{
								expr_val[expr_deep[e_deep - 1]-1][e_deep - 1] = expr_val[expr_deep[e_deep - 1]-1][e_deep - 1] * -1;
								expr_deep[e_deep - 1]--;
								//cerr << "res = " << expr_val[expr_deep-1] << endl;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}
				}
				break;
			case s_no:
				if (cur_comm->is_expr_error == false)
				{
					switch (cur_comm->expr_type) 
					{
						case S_INT:
						case S_FLOAT:
						case S_BOOL:
							if (expr_deep_str[e_deep - 1])
							{
								cur_comm->is_expr_error = true;
								cur_comm->last_expr_error = "incorrect operands";
							}
							else 
							{
								expr_val[expr_deep[e_deep - 1]-1][e_deep - 1] = ! expr_val[expr_deep[e_deep - 1]-1][e_deep - 1];
								expr_deep[e_deep - 1]--;
							}
							break;
						default:
							cur_comm->is_expr_error = true;
							cur_comm->last_expr_error = "incorrect operands";
					}	
				}
				break;
			default: break;
		}
		p++;
	}
	stdout_buf.clear();
}

void SVMachine::prepare_expr_array()
{
	cur_comm->expr_type = S_ARRAY;
	std::string objname;
	SObject *obj;
	get_subobject(&objname, obj);
	cur_comm->expr_obj_left = obj;
	std::string type = ((SClassArray*)obj)->GetArrayType();
	if (type == "Integer")
		cur_comm->is_array_type = S_INT;
	else if (type == "Float")
		cur_comm->is_array_type = S_FLOAT;
	else if (type == "Boolean")
		cur_comm->is_array_type = S_BOOL;
	else if (type == "String")
		cur_comm->is_array_type = S_STRING;
	cur_comm->is_array = true;
}		
	
void SVMachine::id_dotlist_handler()
{
	std::string objname;
	SObject *obj2, *o;
	list<string>::iterator p = cur_comm->buf.begin();
	if ( get_subobject(&objname, obj2) )
	{
		std::string objclass = obj2->GetClassName();
		if (is_get_object && ! cur_comm->is_array_operation)
		{
			s_param *sp = new s_param;
			sp->type = S_OBJECT;
			sp->val = obj2;
			args.push_back(*sp);
			is_get_object = false;
			return;
		}
		if (objclass == "Object") 
		{
			o = ((SClassObject*)obj2)->GetFields()->Get(objname);
		}
		else
		{
			o = obj2;
			if (objclass == "Integer")
			{
				cur_comm->val_int = ((SClassInteger*)obj2)->Get();
				if (cur_comm->na == NUM_INC)
					cur_comm->val_int++;
				else if (cur_comm->na == NUM_DEC) 
					cur_comm->val_int--;
				((SClassInteger*)obj2)->Set(cur_comm->val_int);
				expr_val[expr_deep[e_deep - 1]++][e_deep - 1] = cur_comm->val_int;
				if (cur_comm->is_oper_with_params_now && !cur_comm->is_array_operation && !cur_comm->is_hash_operation)
				{
					int *val = new int;
					*val = cur_comm->val_int;
					s_param *sp = new s_param;
					sp->type = S_INT;
					sp->val = val;
					garbage.push_back(val);
					args.push_back(*sp);
					expr_val[expr_deep[e_deep - 1]++][e_deep - 1] = cur_comm->val_int;
				}
				else if (cur_comm->is_array_operation)
				{
					cur_comm->array_indx = cur_comm->val_int;
					cur_comm->is_ok_array = true;
				}
			} else if (objclass == "Float")
			{
				cerr << "Float\n";
				cur_comm->val_float = ((SClassFloat*)obj2)->Get();
				if (cur_comm->na == NUM_INC)
					cur_comm->val_float++;
				else if (cur_comm->na == NUM_DEC) 
					cur_comm->val_float--;
				((SClassFloat*)obj2)->Set(cur_comm->val_float);
				expr_val[expr_deep[e_deep - 1]++][e_deep - 1] = cur_comm->val_float;
				if (cur_comm->is_oper_with_params_now)
				{
					float *val = new float;
					*val = cur_comm->val_float;
					s_param *sp = new s_param;
					sp->type = S_FLOAT;
					sp->val = val;
					garbage.push_back(val);
					args.push_back(*sp);
					expr_val[expr_deep[e_deep - 1]++][e_deep - 1] = cur_comm->val_float;
				}
				else if (cur_comm->is_array_operation)
				{
					cur_comm->is_ok_array = false;
				}
			} else if (objclass == "String")
			{
				cur_comm->hash_key = ((SClassString*)obj2)->Get();
				expr_val_str[expr_deep_str[e_deep - 1]++][e_deep - 1] = ((SClassString*)obj2)->Get();
				if (cur_comm->is_oper_with_params_now)
				{
					std::string *val = new string;
					*val = ((SClassString*)obj2)->Get();
					s_param *sp = new s_param;
					sp->type = S_STRING;
					sp->val = val;
					garbage.push_back(val);
					args.push_back(*sp);
				}
			}
		}
		if (!cur_comm->is_array_operation)
		{
			objclass = o->GetClassName();
			if (objclass == "Object")
			{
				cerr << "Error. it's Object!\n";
				return;
			}
			s_param buf1;
			o->Invoke("ToString", &buf1, 0);
			std::string s = (*(string*)buf1.val);
			stdout_buf.push_back(s);
		}
	}
}

void SVMachine::expr_post_handler()
{
	double tmp; bool ok = false, oks = false; // oks special for string
	if (cur_comm->is_expr_error)
	{
		return;
	}
	switch (cur_comm->expr_act)
	{
		case e_add:
		{
			switch (cur_comm->expr_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false && expr_deep)
					{
						tmp = ((SClassInteger*)cur_comm->expr_obj_left)->Get();
						tmp += expr_val[0][e_deep - 1];
						((SClassInteger*)cur_comm->expr_obj_left)->Set(tmp);
						ok = true;
					}
					break;
				case S_FLOAT:
					if (cur_comm->is_expr_error == false && expr_deep)
					{
						tmp = ((SClassFloat*)cur_comm->expr_obj_left)->Get();
						tmp += expr_val[0][e_deep - 1];
						((SClassFloat*)cur_comm->expr_obj_left)->Set(tmp);
						ok = true;
					}
					break;
				case S_STRING:
				{
					if (cur_comm->is_expr_error == false && expr_deep)
					{
						std::string tmp = ((SClassString*)cur_comm->expr_obj_left)->Get();
						tmp += expr_val_str[0][e_deep - 1];
						((SClassString*)cur_comm->expr_obj_left)->Set(tmp);
						oks = true;
					}
					break;
				}
				case S_ARRAY:
				{
					expr_array_handler();
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_sub:
		{
			switch (cur_comm->expr_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false && expr_deep)
					{
						//cerr << "\tit's integer\n";
						tmp = ((SClassInteger*)cur_comm->expr_obj_left)->Get();
						//cerr << "expr0="<< expr_val[0] << "; expr1="<< expr_val[1] << endl;
						tmp -= expr_val[0][e_deep - 1];
						//cerr << "\t\tres = " << tmp << endl;
						((SClassInteger*)cur_comm->expr_obj_left)->Set(tmp);
						ok = true;
					}
					break;
				case S_FLOAT:
					if (cur_comm->is_expr_error == false && expr_deep)
					{
						tmp = ((SClassFloat*)cur_comm->expr_obj_left)->Get();
						tmp -= expr_val[0][e_deep - 1];
						((SClassFloat*)cur_comm->expr_obj_left)->Set(tmp);
						ok = true;
					}
					break;
				case S_ARRAY:
				{
					if (cur_comm->is_expr_error == false)
					{
						expr_array_handler();
					}
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_mul:
		{
			switch (cur_comm->expr_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false && expr_deep)
					{
						//cerr << "\tit's integer\n";
						tmp = ((SClassInteger*)cur_comm->expr_obj_left)->Get();
						//cerr << "expr0="<< expr_val[0] << "; expr1="<< expr_val[1] << endl;
						tmp *= expr_val[0][e_deep - 1];
						//cerr << "\t\tres = " << tmp << endl;
						((SClassInteger*)cur_comm->expr_obj_left)->Set(tmp);
						ok = true;
					}
					break;
				case S_FLOAT:
					if (cur_comm->is_expr_error == false && expr_deep)
					{
						tmp = ((SClassFloat*)cur_comm->expr_obj_left)->Get();
						tmp *= expr_val[0][e_deep - 1];
						((SClassFloat*)cur_comm->expr_obj_left)->Set(tmp);
						ok = true;
					}
					break;
				case S_STRING:
					if (expr_deep[e_deep - 1] != 1)
					{
						cur_comm->is_expr_error = true;
						cur_comm->last_expr_error = "only use: %str *= num";
					}
					else if (expr_deep_str[e_deep - 1])
					{
						cur_comm->is_expr_error = true;
						cur_comm->last_expr_error = "only use: %str *= num";
					}
					else 
					{
						std::string tmp = ((SClassString*)cur_comm->expr_obj_left)->Get(), res;
						for (int i = 0; i < (int)expr_val[0]; i++, res += tmp);
						((SClassString*)cur_comm->expr_obj_left)->Set(res);
						oks = true;
					}
					break;
				case S_ARRAY:
				{
					expr_array_handler();
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_div:
		{
			switch (cur_comm->expr_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false && expr_deep[e_deep - 1])
					{
						//cerr << "\tit's integer\n";
						tmp = ((SClassInteger*)cur_comm->expr_obj_left)->Get();
						//cerr << "expr0="<< expr_val[0] << "; expr1="<< expr_val[1] << endl;
						tmp /= expr_val[0][e_deep - 1];
						//cerr << "\t\tres = " << tmp << endl;
						((SClassInteger*)cur_comm->expr_obj_left)->Set(tmp);
						ok = true;
					}
					break;
				case S_FLOAT:
					if (cur_comm->is_expr_error == false && expr_deep[e_deep - 1])
					{
						tmp = ((SClassFloat*)cur_comm->expr_obj_left)->Get();
						tmp /= expr_val[0][e_deep - 1];
						((SClassFloat*)cur_comm->expr_obj_left)->Set(tmp);
						ok = true;
					}
					break;
				case S_ARRAY:
				{
					if (cur_comm->is_expr_error == false)
					{
						expr_array_handler();
					}
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_mod:
		{
			switch (cur_comm->expr_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false && expr_deep[e_deep - 1])
					{
						//cerr << "\tit's integer\n";
						tmp = ((SClassInteger*)cur_comm->expr_obj_left)->Get();
						//cerr << "expr0="<< expr_val[0] << "; expr1="<< expr_val[1] << endl;
						tmp = (int)tmp % (int)expr_val[0][e_deep - 1];
						//cerr << "\t\tres = " << tmp << endl;
						((SClassInteger*)cur_comm->expr_obj_left)->Set(tmp);
						ok = true;
					}
					break;
				case S_ARRAY:
				{
					if (cur_comm->is_expr_error == false)
					{
						expr_array_handler();
					}
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_or:
		{
			switch (cur_comm->expr_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false && expr_deep[e_deep - 1])
					{
						tmp = ((SClassInteger*)cur_comm->expr_obj_left)->Get();
						tmp = (int)tmp | (int)expr_val[0][e_deep - 1];
						((SClassInteger*)cur_comm->expr_obj_left)->Set(tmp);
						ok = true;
					}
					break;
				case S_ARRAY:
				{
					if (cur_comm->is_expr_error == false)
					{
						expr_array_handler();
					}
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_xor:
		{
			switch (cur_comm->expr_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false && expr_deep[e_deep - 1])
					{
						tmp = ((SClassInteger*)cur_comm->expr_obj_left)->Get();
						tmp = (int)tmp ^ (int)expr_val[0][e_deep - 1];
						((SClassInteger*)cur_comm->expr_obj_left)->Set(tmp);
						ok = true;
					}
					break;
				case S_ARRAY:
				{
					if (cur_comm->is_expr_error == false)
					{
						expr_array_handler();
					}
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_and:
		{
			switch (cur_comm->expr_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false && expr_deep[e_deep - 1])
					{
						//cerr << "\tit's integer\n";
						tmp = ((SClassInteger*)cur_comm->expr_obj_left)->Get();
						//cerr << "expr0="<< expr_val[0] << "; expr1="<< expr_val[1] << endl;
						tmp = (int)tmp & (int)expr_val[0][e_deep - 1];
						//cerr << "\t\tres = " << tmp << endl;
						((SClassInteger*)cur_comm->expr_obj_left)->Set(tmp);
						ok = true;
					}
					break;
				case S_ARRAY:
				{
					if (cur_comm->is_expr_error == false)
					{
						expr_array_handler();
					}
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		default:
			break;
	}
	if (ok)
	{
		expr_deep[e_deep - 1]--;
		//cerr << "res = " << expr_val[expr_deep-1] << endl;
	}
	if (oks)
	{
		expr_deep_str[e_deep - 1]--;
	}
}

void SVMachine::expr_array_handler()
{
	bool ok = false, oks = false;
	double tmp = NULL;
	SObject *tobj = ((SClassArray*)cur_comm->expr_obj_left)->Get(cur_comm->is_array_index);
	switch (cur_comm->expr_act)
	{
		case e_add:
		{
			switch (cur_comm->is_array_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false)
					{
						tmp = ((SClassInteger*)tobj)->Get();
						tmp += expr_val[0][e_deep - 1];
						((SClassInteger*)tobj)->Set(tmp);
						ok = true;
					}
					break;
				case S_FLOAT:
					if (cur_comm->is_expr_error == false)
					{
						tmp = ((SClassFloat*)tobj)->Get();
						tmp += expr_val[0][e_deep - 1];
						((SClassFloat*)tobj)->Set(tmp);
						ok = true;
					}
					break;
				case S_STRING:
				{
					if (cur_comm->is_expr_error == false)
					{
						std::string tmp = ((SClassString*)tobj)->Get();
						tmp += expr_val_str[0][e_deep - 1];
						((SClassString*)tobj)->Set(tmp);
						oks = true;
					}
					break;
				}
				case S_ARRAY:
				{
					expr_array_handler();
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_sub:
		{
			switch (cur_comm->is_array_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false)
					{
						tmp = ((SClassInteger*)tobj)->Get();
						tmp -= expr_val[0][e_deep - 1];
						((SClassInteger*)tobj)->Set(tmp);
						ok = true;
					}
					break;
				case S_FLOAT:
					if (cur_comm->is_expr_error == false)
					{
						tmp = ((SClassFloat*)tobj)->Get();
						tmp -= expr_val[0][e_deep - 1];
						((SClassFloat*)tobj)->Set(tmp);
						ok = true;
					}
					break;
				case S_ARRAY:
				{
					if (cur_comm->is_expr_error == false)
					{
						expr_array_handler();
					}
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_mul:
		{
			switch (cur_comm->is_array_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false)
					{
						tmp = ((SClassInteger*)tobj)->Get();
						tmp *= expr_val[0][e_deep - 1];
						((SClassInteger*)tobj)->Set(tmp);
						ok = true;
					}
					break;
				case S_FLOAT:
					if (cur_comm->is_expr_error == false)
					{
						tmp = ((SClassFloat*)tobj)->Get();
						tmp *= expr_val[0][e_deep - 1];
						((SClassFloat*)tobj)->Set(tmp);
						ok = true;
					}
					break;
				case S_STRING:
					if (expr_deep[e_deep - 1] != 1)
					{
						cur_comm->is_expr_error = true;
						cur_comm->last_expr_error = "only use: %str *= num";
					}
					else if (expr_deep_str[e_deep - 1])
					{
						cur_comm->is_expr_error = true;
						cur_comm->last_expr_error = "only use: %str *= num";
					}
					else 
					{
						std::string tmp = ((SClassString*)tobj)->Get(), res;
						for (int i = 0; i < (int)expr_val[0]; i++, res += tmp);
						((SClassString*)tobj)->Set(res);
						oks = true;
					}
					break;
				case S_ARRAY:
				{
					expr_array_handler();
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_div:
		{
			switch (cur_comm->is_array_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false)
					{
						tmp = ((SClassInteger*)tobj)->Get();
						tmp /= expr_val[0][e_deep - 1];
						((SClassInteger*)tobj)->Set(tmp);
						ok = true;
					}
					break;
				case S_FLOAT:
					if (cur_comm->is_expr_error == false)
					{
						tmp = ((SClassFloat*)tobj)->Get();
						tmp /= expr_val[0][e_deep - 1];
						((SClassFloat*)tobj)->Set(tmp);
						ok = true;
					}
					break;
				case S_ARRAY:
				{
					if (cur_comm->is_expr_error == false)
					{
						expr_array_handler();
					}
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_mod:
		{
			switch (cur_comm->is_array_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false)
					{
						tmp = ((SClassInteger*)tobj)->Get();
						tmp = (int)tmp % (int)expr_val[0][e_deep - 1];
						((SClassInteger*)tobj)->Set(tmp);
						ok = true;
					}
					break;
				case S_ARRAY:
				{
					if (cur_comm->is_expr_error == false)
					{
						expr_array_handler();
					}
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_or:
		{
			switch (cur_comm->is_array_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false)
					{
						tmp = ((SClassInteger*)tobj)->Get();
						tmp = (int)tmp | (int)expr_val[0][e_deep - 1];
						((SClassInteger*)tobj)->Set(tmp);
						ok = true;
					}
					break;
				case S_ARRAY:
				{
					if (cur_comm->is_expr_error == false)
					{
						expr_array_handler();
					}
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_xor:
		{
			switch (cur_comm->is_array_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false)
					{
						tmp = ((SClassInteger*)tobj)->Get();
						tmp = (int)tmp ^ (int)expr_val[0][e_deep - 1];
						((SClassInteger*)tobj)->Set(tmp);
						ok = true;
					}
					break;
				case S_ARRAY:
				{
					if (cur_comm->is_expr_error == false)
					{
						expr_array_handler();
					}
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		case e_and:
		{
			switch (cur_comm->is_array_type) 
			{
				case S_INT:
					if (cur_comm->is_expr_error == false)
					{
						tmp = ((SClassInteger*)tobj)->Get();
						tmp = (int)tmp & (int)expr_val[0][e_deep - 1];
						((SClassInteger*)tobj)->Set(tmp);
						ok = true;
					}
					break;
				case S_ARRAY:
				{
					if (cur_comm->is_expr_error == false)
					{
						expr_array_handler();
					}
					break;
				}
				default:
					cur_comm->is_expr_error = true;
					cur_comm->last_expr_error = "incorrect operands";
			}	
			break;
		}
		default:
			break;
	}
}

bool SVMachine::expr_test_string()
{
	return (expr_deep_str[e_deep - 1] != 0);
}

bool SVMachine::check_object(std::string name, SRegistryObj *reg)
{
	if (reg->Get(name) != NULL)
		return true;
	else
		return false; 
}

SObject* SVMachine::find_object(std::string name)
{
	SObject *res = global[level]->Get(name);
	if (res == NULL) 
	{
		for (int i = level; i >= 0 && res == NULL; res = global[i]->Get(name), i--);
	}
	return res;
}

s_param SVMachine::get_last_arg()
{
	s_param res;
	param_list::iterator p = args.begin();
	while (p != args.end())
	{
		cerr << *((int*)p->val) << " " ;
		p++;
	}
	if (p != args.begin())
	{
		p--;
		res = *p;
		args.pop_back();
	}
	return res;
}

bool SVMachine::get_subobject(std::string *objname, SObject *&obj2)
{
	int deep = 0;
	bool itsop = false;
	list<string> qbuf;
	if ( ! pbuf.size() )
		qbuf = cur_comm->buf;
	else
		qbuf = pbuf;
	list<string>::iterator p = qbuf.begin();
	p = qbuf.begin();
	std::string object_name = *p;
	p++;
	deep++;
	SObject *obj = find_object(object_name);
	if ( !obj )
	{
 		p--;
		cerr << "No object - " << p->c_str() << "! Terminate.\n";
		return false;
	}
	s_param buf1;
	obj->Invoke("ClassName", &buf1, 0);
	if ( (p == qbuf.end() && ! cur_comm->is_oper_with_params_now) || is_spec_op_flag ) 
	{
		obj2 = obj;
		*objname = object_name;
		if (is_spec_op_flag)
			is_spec_op_flag = false;
		return true;
	} else if (cur_comm->is_oper_with_params_now) {
		if (! cur_comm->is_array_operation)
			return params_handler(2, objname, obj2);
		else
			return params_handler(1, objname, obj2);
	} else if ( (*(string*)buf1.val) != "Object" )
	{
		cerr << "\nMust be Object only!\n";
		return false;
	} 
	if (cur_comm->is_oper_with_params_now || cur_comm->is_array_operation)
	{
		cerr << "incorrent index! level limited by 1 in this version\n";
		return false;
	}
	
	s_param obj_ref, obj_n;
	param_list *prep = new param_list();
	while ( p != qbuf.end() )
	{
		std::string s = *p;
		p++;
		if (p != qbuf.end() )
		{
			prep->clear();
			obj_n.val = (void*)&s;
			obj_n.type = S_STRING;
			prep->push_back(obj_n);
			SClassObject::GetField(obj, &obj_ref, prep);
			if (obj_ref.val == NULL)
			{
				cerr << "No field - " << s.c_str() << "! Terminate.\n";
				return false;
			}
			else
				obj = (SObject*)obj_ref.val;
		}
		else
		{
			*objname = s;
		}
	}
	qbuf.clear();
	obj2 = (SClassObject*)obj;
	return true;
}

bool SVMachine::params_handler(int deep, std::string *objname, SObject *&obj2)
{
	list<string>::iterator p = cur_comm->buf.begin();
	for (int i = 0; i < deep; i++, p++);
	while (true)
	{
		if (p == cur_comm->buf.end())
		{
			break;
		}
		else
		{
			pbuf.push_back(*p);
			p++;
		}
	}
	p = cur_comm->buf.begin();
	for (int i = 0; i < deep; i++, p++);
	cur_comm->buf.erase(p);
	cur_comm->tmpbuf.push_back(*p);
	is_spec_op_flag = true;
	get_subobject(objname, obj2);
		
	pbuf.clear();
	cur_comm->buf.push_back(*p);
	if (obj2 == NULL)
		return false;
	else
	{
		is_get_object = true;
		return true;
	}
}

void SVMachine::delete_operation()
{
	list<string>::iterator p = cur_comm->buf.begin();
	std::string object_name = *p;
	SObject *obj2 = global[level]->Get(object_name);
	if ( !obj2 )
	{
		cerr << "No object - " << p->c_str() << "! Terminate.\n";
		return;
	}
	p++;
	s_param obj_ref, obj_n, buf1;
	param_list *prep = new param_list();
	if ( p == cur_comm->buf.end() )
	{
		global[level]->Remove(object_name);
		return;
	}
	else
	{
		s_param buf1;
		obj2->Invoke("ClassName", &buf1, 0);
		if ( (*(string*)buf1.val) != "Object" )
		{
			cerr << "\nMust be Object only!\n";
			return;
		} 
	}
	while ( p != cur_comm->buf.end() )
	{
		std::string stmp = *p;
		p++;
		if (p == cur_comm->buf.end())
		{
			prep->clear();
			obj_n.val = (void*)&stmp;
			obj_n.type = S_STRING;
			prep->push_back(obj_n);
			SClassObject::GetField(obj2, &obj_ref, prep);
			if (obj_ref.val == NULL)
			{
				cerr << "No field - " << stmp.c_str() << "! Terminate.\n";
				return;
			}
			else
			{
				((SClassObject*)obj2)->GetFields()->Remove(stmp);
			}
		}
		else
		{
			prep->clear();
			obj_n.val = (void*)&stmp;
			obj_n.type = S_STRING;
			prep->push_back(obj_n);
			SClassObject::GetField(obj2, &obj_ref, prep);
			if (obj_ref.val == NULL)
			{
				cerr << "No field - " << stmp.c_str() << "! Terminate.\n";
				return;
			}
			else
				obj2 = (SObject*)obj_ref.val;
		}
	}
}

void SVMachine::operation(bool is_string, bool is_params)
{
	list<string>::iterator p = cur_comm->buf.begin();
	std::string object_name = *p;
	SObject *obj2 = find_object(object_name);
	if (object_name == "this")
	{
		obj2 = value[value_deep - 1];
		if (! obj2)
		{
			cerr << "'this' must using only in methods!\n";
			return;
		}
	}
	else if ( !obj2 )
	{
		cerr << "No object - " << p->c_str() << "! Terminate.\n";
		return;
	}
	p++;
	s_param obj_ref, obj_n, buf1;
	param_list *prep = new param_list();
	if ( p == cur_comm->buf.end() )
	{
		obj2->Invoke("ToString", &buf1, 0);
		std::string s = (*(string*)buf1.val);
		stdout_buf.push_back(s);
		return;
	}
	while ( p != cur_comm->buf.end() )
	{
		std::string stmp = *p;
		p++;
		if (p == cur_comm->buf.end())
		{
			if (is_string == false)
			{
				if (is_params == false)
				{
					memset(&buf1, '\0', sizeof(s_param));
					std::string cn = obj2->GetClassName();
					if (cn == "Integer") {
						s_methods::iterator p = t_integer.find(stmp);
						if (p != t_integer.end())
						{
							call_method(obj2, p->second);
							return;
						}
					} else if (cn == "Float") {
						s_methods::iterator p = t_float.find(stmp);
						if (p != t_float.end())
						{
							call_method(obj2, p->second);
							return;
						}
					} else if (cn == "String") {
						s_methods::iterator p = t_string.find(stmp);
						if (p != t_string.end())
						{
							call_method(obj2, p->second);
							return;
						}
					}
					if (obj2->Invoke(stmp, &buf1, 0) == S_INVOKE_NOMETHOD)
						cerr << "No method - " << stmp << endl;
					else
					{
						if (buf1.val)
						{
							operation_expr(buf1);
						}
					}
				}
				else
				{
					memset(&buf1, '\0', sizeof(s_param));
					std::string cn = obj2->GetClassName();
					if (cn == "Integer") {
						s_methods::iterator p = t_integer.find(stmp);
						if (p != t_integer.end())
						{
							call_method(obj2, p->second, true);
							return;
						}
					} else if (cn == "Float") {
						s_methods::iterator p = t_float.find(stmp);
						if (p != t_float.end())
						{
							call_method(obj2, p->second, true);
							return;
						}
					} else if (cn == "String") {
						s_methods::iterator p = t_string.find(stmp);
						if (p != t_string.end())
						{
							call_method(obj2, p->second, true);
							return;
						}
					}
					
					S_RESULTS sres = (S_RESULTS)obj2->Invoke(stmp, &buf1, &args);
					
					garbage.clear();
					args.clear();
					if (sres == S_INVOKE_NOMETHOD)
						cerr << "No method - " << stmp << endl;
					else if (sres == S_INVOKE_INCORRECT)
						cerr << "Incorrect arguments!" << endl;
					else
					{
						if (buf1.val)
						{
							operation_expr(buf1);
						}
					}
				}	
			}
			else
			{
				prep->clear();
				obj_n.val = (void*)&stmp;
				obj_n.type = S_STRING;
				prep->push_back(obj_n);
				SClassObject::GetField(obj2, &obj_ref, prep);
				if (obj_ref.val == NULL)
				{
					cerr << "No field - " << stmp.c_str() << "! Terminate.\n";
					return;
				}
				else
					obj2 = (SObject*)obj_ref.val;
				obj2->Invoke("ToString", &buf1, 0);
				std::string s = (*(string*)buf1.val);
				operation_expr(buf1);
			}
		}
		else
		{
			prep->clear();
			obj_n.val = (void*)&stmp;
			obj_n.type = S_STRING;
			prep->push_back(obj_n);
			SClassObject::GetField(obj2, &obj_ref, prep);
			if (obj_ref.val == NULL)
			{
				cerr << "No field - " << stmp.c_str() << "! Terminate.\n";
			}
			else
				obj2 = (SObject*)obj_ref.val;
		}
	}
}

void SVMachine::operation_expr(s_param &prm)
{
	switch (prm.type)
	{
		case S_STRING:
		{
			std::string s = (*(string*)prm.val);	
			if (cur_comm->parent && ( cur_comm->parent->comm == s_put || cur_comm->parent->comm == s_puts ) )
			{
				stdout_buf.push_back(s);
			}
			expr_val_str[expr_deep_str[e_deep - 1]++][e_deep - 1] = s;
			break;
		}
		case S_INT:
		{
			expr_val[expr_deep[e_deep - 1]++][e_deep - 1] = *((int*)prm.val);
			if (cur_comm->parent && ( cur_comm->parent->comm == s_put || cur_comm->parent->comm == s_puts ) )
			{
				std::string t = SClassInteger::itoa(*((int*)prm.val), 10);
				stdout_buf.push_back(t);
			}
			delete ((int*)prm.val);
			break;
		}	
		case S_BOOL:
		{
			expr_val[expr_deep[e_deep - 1]++][e_deep - 1] = *((bool*)prm.val);
			if (cur_comm->parent && ( cur_comm->parent->comm == s_put || cur_comm->parent->comm == s_puts ) )
			{
				if (*((bool*)prm.val))
					stdout_buf.push_back("true");
				else
					stdout_buf.push_back("false");
			}
			break;
		}
		default: break;
	}
		
}

void SVMachine::input_string(SObject *o)
{
	if ( !o )
	{
		cerr << "Some engine error. sorry\n";
		return;
	}
	s_param buf1;
	memset( &buf1, '\0', sizeof(s_param) );
	o->Invoke("ClassName", &buf1, 0);
	if ( !buf1.val || (*(string*)buf1.val) != "String" )
	{
		std::cerr << "\nMust be String only!\n";
	} 
	else
	{
		cerr << "> ";
		
		char bufs[255];
	
		cerr.flush();
		cin.clear();
		
		cerr.sync_with_stdio(true);
		cout.sync_with_stdio(true);
		cin.sync();
		
		cin >> bufs;
		
		std::string s = bufs;
		
		((SClassString*)o)->Set(s);
	}	
}

void SVMachine::put_out(bool _endl)
{
	list<string>::iterator p = stdout_buf.begin();
	while ( p != stdout_buf.end() )
	{
		cerr << *p;
		p++;
	}
	stdout_buf.clear();
	if (_endl)
	{
		cerr << std::endl;
	}
	cerr << endl;
}
